#ifndef __MY__SERVICE__
#define __MY__SERVICE__
#include"httplib.h"
#include"util.hpp"
#include"config.hpp"
#include<time.h>
extern cloud::DataManager *_data;
namespace cloud{
	class Service{
		//搭建服务器，进行业务处理
		//有三个请求upload、listshow、download
		private:
		int _server_port;
		std::string _server_ip;
		std::string _download_prefix;
		httplib::Server _server;
		static void Upload(const httplib::Request &req,httplib::Response &rsp){
			if(req.has_file("file")==false)
				return ;
			//获取req中的文件，再创建一个文件放入储存路径
			const auto & file=req.get_file_value("file");
			//file.filename--文件名  file.content--文件内容
			std::string back_dir=Config::GetInstance()->GetBackDir();
			//怕传过来的文件名含有多个‘/’怕坏文件名统一性

			std::string realpath=back_dir+FileUtil(file.filename).FileName();//文件储存在back_path
			FileUtil fu(realpath);

			fu.SetContent(file.content);//将数据写入文件中

			BackInfo bi;
			bi.NewBackInfo(realpath);
			_data->Insert(bi);	
			return ;
		}
		static std::string TimeToStr(time_t time){
			return std::ctime(&time);	
			
		}
		static void ListShow(const httplib::Request &req,httplib::Response &rsp){
			//先获取所有文件数据，然后遍历依次返回数据
			std::vector<BackInfo > arry;
			_data->GetAll(&arry);
			//接下来组织html页面信息
			std::stringstream ss;
			ss<<"<html><head><title>Download</title></head>";
			ss<<"<body><h1>Download</h1><table>";
			for(auto &a:arry){
				ss<<"<tr>";	
				std::string filename =FileUtil(a._real_path).FileName();
				ss<<"<td><a href='"<<a._url<<"'>"<<filename<<"</a></td>";//写入下载地址
				ss<<"<td align='right'>"<<TimeToStr(a._mtime)<<"</td>";
				ss<<"<td align='right'>"<<a._fsize/1024<<"k </td>";
				ss<<"</tr>";
			}
			ss<<"</table></body></html>";
			rsp.body=ss.str();
			rsp.set_header("Content-Type","text/html");
			rsp.status=200;
			return ;
		}
		
		static std::string GetETag(BackInfo info){
			//filename-fsize-lastmtime
			FileUtil fu(info._real_path);
			std::string etag;
			etag+=fu.FileName();
			etag+="-";
			etag+=info._fsize;
			etag+="-";
			etag+=info._mtime;
			return etag;
		}
		static void Download(const httplib::Request &req,httplib::Response &rsp){
			//获取路径，然后获取文件信息
			BackInfo bi;
			_data->GetOneByUrl(req.path,&bi);//该路径其实就是网页申请的下载路径
			//查看是否压缩，压缩就解压缩
			if(bi._pack_flag==true){
				//解压缩后要删除压缩包，更改压缩信息
				FileUtil fu(bi._pack_path);      
				fu.UnCompress(bi._real_path);
				fu.Remove();
				bi._pack_flag=false;
				_data->Updata(bi);
			}
			//获取etag并将其和客户端传上来的进行对比
			std::string etag;
			int retrans=false;
			if(req.has_header("If-Range")){
				etag=req.get_header_value("If-Range");
				if(etag==GetETag(bi)){
					retrans=true;
				}
			}
			//读取文件内容，写入rsp
			FileUtil fu2(bi._real_path);
			if(retrans==false){
				fu2.GetContent(&rsp.body);
				//返回header
				rsp.set_header("Accept-Ranges","bytes");
				rsp.set_header("ETag",GetETag(bi));
				rsp.set_header("Content-Type","application/octet-stream");//说明这是一个二进制数据流，表现在网页上就是点击即可下载
				rsp.status=200;
			}
			else{
				//httplib内部实现了我们的取件请求也就是断点续传的处理
				//只需要用户将文件读取到rsp.body里去，它内部会根据请求区间，从body中取出指定区间数据进行响应。
				fu2.GetContent(&rsp.body);
				rsp.set_header("Accept-Ranges","bytes");
				rsp.set_header("Content-Type","application/octet-stream");//说明这是一个二进制数据流，表现在网页上就是点击即可下载
				rsp.set_header("ETag",GetETag(bi));
				rsp.status=206;
			}
			return ;
		}
		
		public:
		Service(){
			Config *config=Config::GetInstance();
			_download_prefix=config->GetDownloadPrefix();	
			_server_port=config->GetServerPort();	
			_server_ip=config->GetServerIp();
			//编译器会自己调用Server的默认构造函数		
		}
		void RunModule(){
			_server.Post("/upload",Upload);
			_server.Get("/showlist",ListShow);
			_server.Get("/",ListShow);
			std::string download_url=_download_prefix+"(.*)";
			_server.Get(download_url,Download);
			_server.listen(_server_ip.c_str(),_server_port);//110.41.149   9090
		}
};
	
	
	
	
}



#endif